package com.yy.finvideoplayer.media

import android.content.Context
import android.view.Surface
import android.view.SurfaceHolder
import com.google.android.exoplayer2.*
import com.google.android.exoplayer2.source.MediaSource
import com.google.android.exoplayer2.video.VideoSize

/**
 * @Description: ExoPlayer 2.x 基础媒体播放器，适配原 IjkBaseMedia 接口
 * @Author: yiw89
 * @CreateDate: 2025/10/22
 * @Version: 1.0
 */
abstract class ExoBaseMedia(iMediaCallback: IMediaCallback) :
    BaseMedia(iMediaCallback),
    Player.Listener {

    var player: ExoPlayer? = null
    private var mediaSource: MediaSource? = null

    override fun doPrepare(
        context: Context,
        url: String,
        headers: Map<String, String?>?,
        vararg objects: Any?
    ): Boolean {
        try {
            release()

            // 创建 ExoPlayer
            player = createPlayer(context)
            player?.addListener(this)

            // 创建 MediaSource
            mediaSource = createMediaSource(context, url, headers)
            if (mediaSource == null) {
                onError(null, ExoPlayerError.ERROR_CODE_IO_NETWORK, 0)
                return false
            }

            // 配置播放器
            player?.repeatMode = if (isLooping) Player.REPEAT_MODE_ONE else Player.REPEAT_MODE_OFF


            // 准备播放
            player?.setMediaSource(mediaSource!!)
            player?.prepare()
            return true
        } catch (e: Exception) {
            e.printStackTrace()
            onError(null, ExoPlayerError.ERROR_CODE_GENERIC, 0)
            return false
        }
    }

    // 添加缺失的 onError 方法
    protected fun onError(player: ExoPlayer?, what: Int, extra: Int) {
        iMediaCallback.onError(this, what, extra)
        isPrepar = false
    }

    /**
     * 创建 ExoPlayer 实例（子类可重写自定义配置）
     */
    open fun createPlayer(context: Context): ExoPlayer {
        return ExoPlayer.Builder(context).build()
    }

    /**
     * 创建 MediaSource（核心方法，子类必须实现）
     */
    @Throws(Exception::class)
    abstract fun createMediaSource(
        context: Context,
        url: String,
        headers: Map<String, String?>?
    ): MediaSource?

    override fun setSurface(surface: Surface) {
        try {
            player?.setVideoSurface(surface)
            this.surface = surface
        } catch (e: Exception) {
            e.printStackTrace()
            iMediaCallback.onError(this, ExoPlayerError.ERROR_CODE_GENERIC, 0)
        }
    }

    override fun setDisplay(surfaceHolder: SurfaceHolder?) {
        try {
            player?.setVideoSurfaceHolder(surfaceHolder)
            if (surfaceHolder != null) this.surface = surfaceHolder.surface
        } catch (e: Exception) {
            e.printStackTrace()
            iMediaCallback.onError(this, ExoPlayerError.ERROR_CODE_GENERIC, 0)
        }
    }

    override fun doPlay() {
        if (!isPrepar) return
        player?.playWhenReady = true
    }

    override fun doPause() {
        if (!isPrepar) return
        player?.pause()
    }

    override fun seekTo(duration: Int) {
        if (!isPrepar) return
        player?.seekTo(duration.toLong())
    }

    override fun getCurrentPosition(): Int {
        if (!isPrepar) return 0
        return try {
            player?.currentPosition?.toInt() ?: 0
        } catch (e: Exception) {
            e.printStackTrace()
            0
        }
    }

    override fun getDuration(): Int {
        if (!isPrepar) return 0
        return try {
            player?.duration?.toInt() ?: 0
        } catch (e: Exception) {
            e.printStackTrace()
            0
        }
    }

    override fun getVideoHeight(): Int {
        if (!isPrepar) return 0
        return player?.videoSize?.height ?: 0
    }

    override fun getVideowidth(): Int {
        if (!isPrepar) return 0
        return player?.videoSize?.width ?: 0
    }

    override fun isPlaying(): Boolean {
        if (!isPrepar) return false
        return player?.isPlaying == true
    }

    override fun setVolume(leftVol: Float, rightVol: Float): Boolean {
        if ((leftVol < 0) || (rightVol < 0) || (leftVol > 1) || (rightVol > 1)) return false
        if (isPrepar) {
            val volume = (leftVol + rightVol) / 2f
            player?.volume = volume
        }
        return this is ExoMedia // 类似 IjkMedia 的判断
    }

    override fun setLooping(isLooping: Boolean) {
        this.isLooping = isLooping
        player?.repeatMode = if (isLooping) Player.REPEAT_MODE_ONE else Player.REPEAT_MODE_OFF
    }

    override fun release() {
        isPrepar = false
        preparedFired = false  // ← 释放时重置
        this.surface = null
        player?.let {
            it.removeListener(this)
            it.stop()
            it.clearMediaItems()
            it.release()
        }
        player = null
        mediaSource = null
    }

    ///////////////// ExoPlayer.Listener 回调适配 IMediaCallback /////////////////
    private var preparedFired = false  // ← 添加防重复标志
    override fun onPlaybackStateChanged(playbackState: Int) {
        when (playbackState) {
            Player.STATE_READY -> {
                /*if (!isPrepar && !preparedFired) {  // ← 双重保护
                    preparedFired = true
                    isPrepar = true
                    iMediaCallback.onPrepared(this)
                }*/
                isPrepar = true
                // 延迟100ms确保稳定，避免抖动
                mainThreadHandler.postDelayed({
                    if (!preparedFired) {
                        preparedFired = true
                        iMediaCallback.onPrepared(this)
                    }
                }, 100)
            }
            Player.STATE_ENDED -> {
                preparedFired = false  // ← 重置标志
                iMediaCallback.onCompletion(this)
            }
            Player.STATE_BUFFERING -> {
                // 开始缓冲
            }
            Player.STATE_IDLE -> {
                // 播放器空闲
            }
        }
    }

    override fun onIsPlayingChanged(isPlaying: Boolean) {
        // 播放状态变化
    }

    override fun onPlayerError(error: PlaybackException) {
        val what = when (// 所有网络错误 → IO_NETWORK
            error.errorCode) {
            in 1000..1999 -> ExoPlayerError.ERROR_CODE_IO_NETWORK

            // 所有解析错误 → PARSING
            in 2000..2999 -> ExoPlayerError.ERROR_CODE_PARSING

            // 所有解码错误 → DECODING
            in 3000..3999 -> ExoPlayerError.ERROR_CODE_DECODING
            else -> ExoPlayerError.ERROR_CODE_GENERIC
        }
        iMediaCallback.onError(this, what, error.errorCode)
        isPrepar = false
    }

    override fun onVideoSizeChanged(videoSize: VideoSize) {
        iMediaCallback.onVideoSizeChanged(this, videoSize.width, videoSize.height)
    }

    override fun onMediaItemTransition(mediaItem: MediaItem?, reason: Int) {
        // 媒体切换
    }

    override fun onPositionDiscontinuity(reason: Int) {
        // 位置不连续（如 seek 完成）
        if (reason == Player.DISCONTINUITY_REASON_SEEK) {
            iMediaCallback.onSeekComplete(this)
        }
    }

    // 缓冲更新（定时器模拟 onBufferingUpdate）
    private var bufferingRunnable: Runnable? = null

    private fun startBufferingMonitor() {
        stopBufferingMonitor()
        bufferingRunnable = object : Runnable {
            override fun run() {
                if (isPrepar && player != null) {
                    val bufferedPercentage = player!!.bufferedPercentage
                    iMediaCallback.onBufferingUpdate(this@ExoBaseMedia, bufferedPercentage / 100f)
                }
                player?.let {
                    if (it.isPlaying) mainThreadHandler.postDelayed(this, 1000)
                }
            }
        }
        mainThreadHandler.postDelayed(bufferingRunnable!!, 500)
    }

    private fun stopBufferingMonitor() {
        bufferingRunnable?.let {
            mainThreadHandler.removeCallbacks(it)
            bufferingRunnable = null
        }
    }

    override fun onPlayWhenReadyChanged(playWhenReady: Boolean, reason: Int) {
        super.onPlayWhenReadyChanged(playWhenReady, reason)
        if (playWhenReady) {
            startBufferingMonitor()
        } else {
            stopBufferingMonitor()
        }
    }

    // 兼容旧接口的 onInfo/onSeekComplete
    override fun onTracksChanged(tracks: Tracks) {}
    override fun onLoadingChanged(isLoading: Boolean) {}
    override fun onRenderedFirstFrame() {
        // 首帧渲染完成，双重确认
        if (isPrepar && !preparedFired) {
            preparedFired = true
            iMediaCallback.onPrepared(this)
        }
    }
}